import hashlib
import shutil
from pathlib import Path
from tempfile import NamedTemporaryFile
from urllib.parse import urlparse

from configmanager import CONFIG
from logger import LOGGER


class CacheManager:
    def __init__(self, cache_dir):
        self.cache_dir = Path(cache_dir)
        self.cache_dir.mkdir(parents=True, exist_ok=True)

    def should_cache(self, content_type):
        """检查是否应该缓存该类型内容"""
        binary_types = [
            'application/octet-stream',
            'application/x-binary',
            'application/x-tar',
            'application/zip',
            'application/x-gzip',
            'application/x-7z-compressed'
        ]
        return any(t in content_type for t in binary_types)

    def _get_cache_path(self, url):
        """根据URL生成缓存路径"""
        url_hash = hashlib.md5(url.encode()).hexdigest()
        path_parts = urlparse(url).path.split('/')
        subdir = path_parts[1] if len(path_parts) > 1 else 'other'
        return self.cache_dir / subdir / f"{url_hash}.cache"

    def get(self, url):
        """从缓存获取内容（返回文件路径，支持流式读取）"""
        cache_file = self._get_cache_path(url)
        if cache_file.exists():
            LOGGER.debug(f"Cache hit for URL: {url}")
            return cache_file  # 返回文件路径而非直接读取内容
        LOGGER.debug(f"Cache miss for URL: {url}")
        return None

    def stream_set(self, url):
        """
        流式缓存写入器：返回临时文件对象和最终提交缓存的回调函数
        
        用法：
            temp_file, commit = cache_manager.stream_set(url)
            for chunk in response.iter_content():
                temp_file.write(chunk)  # 流式写入临时文件
                yield chunk  # 同时转发给客户端
            commit()  # 完成后提交缓存
        """
        LOGGER.debug(f"Initializing stream cache for URL: {url}")

        # 创建临时文件（关闭时不自动删除）
        temp_file = NamedTemporaryFile(
            mode='wb',
            delete=False,
            dir=str(self.cache_dir / "temp")  # 临时文件统一放在temp子目录
        )
        self.cache_dir.joinpath("temp").mkdir(parents=True, exist_ok=True)
        
        # 生成最终缓存路径
        final_path = self._get_cache_path(url)
        
        def commit():
            """提交缓存：将临时文件移动到最终位置"""
            temp_file.close()
            try:
                # 确保目标目录存在
                final_path.parent.mkdir(parents=True, exist_ok=True)
                # 移动临时文件到最终路径（原子操作，避免不完整缓存）
                shutil.move(temp_file.name, final_path)
                LOGGER.debug(f"Cache committed for URL: {url}")
            except Exception as e:
                LOGGER.error(f"缓存提交失败: {e}")
                # 清理临时文件
                if Path(temp_file.name).exists():
                    Path(temp_file.name).unlink()
        
        return temp_file, commit

    def clean_temp_files(self):
        """清理未提交的临时文件（可定期调用）"""
        temp_dir = self.cache_dir / "temp"
        if temp_dir.exists():
            LOGGER.debug(f"Cleaning temp files in: {temp_dir}")
            for file in temp_dir.glob("*"):
                try:
                    file.unlink()
                    LOGGER.debug(f"Removed temp file: {file.name}")
                except Exception as e:
                    LOGGER.warning(f"Failed to remove temp file {file.name}: {e}")


# 初始化缓存管理器（根据配置决定是否启用）
CACHE_MANAGER = CacheManager(CONFIG.cache.directory) if CONFIG.cache.enabled else None
